﻿/*
 PennyAuctionTracker
 Copyright (C) 2011  Devin Bileck
 
 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software Foundation;
 either version 2 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with this program;
 if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

using System;
using System.Collections;
using System.Windows.Forms;

namespace PennyAuctionTracker
{
	/// <summary>
	/// Implements a list view column sorter.
	/// </summary>
	public class ListViewColumnSorter : IComparer
	{
		/// <summary>
		/// Sortable data types.
		/// </summary>
	    public enum SortType : int
	    {
	        Text,
	        Number,
	        DateTime
	    }
	    
	    /// <summary>
	    /// The type of data sorting.
	    /// </summary>
	    private SortType typeToSort = SortType.Text;
	    
	    /// <summary>
	    /// The type of data sorting (default is text sorting).
	    /// </summary>
	    public SortType TypeToSort
	    {
	        get { return typeToSort; }
	        set { typeToSort = value; }
	    }
		
	    /// <summary>
	    /// The column index that is being sorted.
	    /// </summary>
	    private int ColumnToSort;
	    
	    /// <summary>
	    /// The order in which to sort (i.e. Ascending/Descending).
	    /// </summary>
	    private SortOrder OrderOfSort;
		
	    /// <summary>
	    /// Case insensitive comparer object.
	    /// </summary>
	    private CaseInsensitiveComparer ObjectCompare;
		
	    /// <summary>
	    /// Class constructor.
	    /// </summary>
	    public ListViewColumnSorter()
	    {
	        ColumnToSort = 0;
	        OrderOfSort = SortOrder.None;
	        ObjectCompare = new CaseInsensitiveComparer();
	    }
		
	    /// <summary>
	    /// Compares the two objects passed using a case insensitive comparison.
	    /// </summary>
	    /// <param name="x">First object to be compared.</param>
	    /// <param name="y">Second object to be compared.</param>
	    /// <returns>The result of the comparison; zero if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'.</returns>
	    public int Compare(object x, object y)
	    {
	        DummyProvider provider = new DummyProvider();
	        int compareResult = 0;
	        
	        // Cast the objects to be compared to ListViewItem objects
	        ListViewItem listviewX = (ListViewItem)x;
	        ListViewItem listviewY = (ListViewItem)y;
	        
	        // Determine the type of data to compare
            int i;
	        bool isXNumeric = int.TryParse(listviewX.SubItems[ColumnToSort].Text, out i);
	        bool isYNumeric = int.TryParse(listviewY.SubItems[ColumnToSort].Text, out i);
	        DateTime dateTime;
	        bool isXDateTime = DateTime.TryParse(listviewX.SubItems[ColumnToSort].Text, out dateTime);
	        bool isYDateTime = DateTime.TryParse(listviewY.SubItems[ColumnToSort].Text, out dateTime);
	        if (isXNumeric && isYNumeric) {	typeToSort = SortType.Number; }
	        else if (isXDateTime && isYDateTime) { typeToSort = SortType.DateTime; }
	        else { typeToSort = SortType.Text; }

	        // Compare the two items
	        if (typeToSort == SortType.Text)
	        {
	            compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
	        }
	        else if (typeToSort == SortType.Number)
	        {
	            try
	            {
	                if (Convert.ToInt32(listviewX.SubItems[ColumnToSort].Text) > Convert.ToInt32(listviewY.SubItems[ColumnToSort].Text))
	                {
	                    compareResult = 1;
	                }
	                else if (Convert.ToInt32(listviewX.SubItems[ColumnToSort].Text) < Convert.ToInt32(listviewY.SubItems[ColumnToSort].Text))
	                {
	                    compareResult = -1;
	                }
	                else
	                {
	                    compareResult = 0;
	                }
	            }
	            catch (Exception e)
	            {
	                MessageBox.Show(e.Message);
	            }
	        }
	        else if (typeToSort == SortType.DateTime)
	        {
	            try
	            {
	                if (listviewX.SubItems[ColumnToSort].Text != "")
	                {
	                    if (Convert.ToDateTime(listviewX.SubItems[ColumnToSort].Text, provider) > Convert.ToDateTime(listviewY.SubItems[ColumnToSort].Text, provider))
	                    {
	                        compareResult = 1;
	                    }
	                    else if (Convert.ToDateTime(listviewX.SubItems[ColumnToSort].Text, provider) < Convert.ToDateTime(listviewY.SubItems[ColumnToSort].Text, provider))
	                    {
	                        compareResult = -1;
	                    }
	                    else
	                    {
	                        compareResult = 0;
	                    }
	                }
	                else
	                {
	                    compareResult = 0;
	                }
	            }
	            catch (Exception e)
	            {
	                MessageBox.Show(e.Message);
	            }
	        }

	        // Calculate correct return value based on object comparison
	        if (OrderOfSort == SortOrder.Ascending)
	        {
	            // Ascending sort is selected, return normal result of compare operation
	            return compareResult;
	        }
	        else if (OrderOfSort == SortOrder.Descending)
	        {
	            // Descending sort is selected, return negative result of compare operation
	            return (-compareResult);
	        }
	        else
	        {
	            // Return zero to indicate they are equal
	            return 0;
	        }
	    }

	    /// <summary>
	    /// Gets or sets the column index to apply the sorting operation (defaults to '0').
	    /// </summary>
	    public int SortColumn
	    {
	        set { ColumnToSort = value; }
	        get { return ColumnToSort; }
	    }

	    /// <summary>
	    /// Gets or sets the order in which to sort (i.e. Ascending/Descending).
	    /// </summary>
	    public SortOrder Order
	    {
	        set { OrderOfSort = value; }
	        get { return OrderOfSort; }
	    }
	}
	
	/// <summary>
	/// Implements a dummy format provider for DateTime conversion.
	/// </summary>
	public class DummyProvider : IFormatProvider
	{
	    // Normally, GetFormat returns an object of the requested type
	    // (usually itself) if it is able; otherwise, it returns nothing.
	    public object GetFormat(Type argType)
	    {
	        // Here, GetFormat displays the name of argType, after removing
	        // the namespace information. GetFormat always returns null.
	        string argStr = argType.ToString();
	        if (argStr == "") { argStr = "Empty"; }
	        argStr = argStr.Substring(argStr.LastIndexOf('.'),   1);
	        Console.Write("{0,-20}", argStr);
	        return null;
	    }
	}
}